package com.wuliu.system.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wuliu.common.constant.OrderConstants;
import com.wuliu.common.core.domain.PageResult;
import com.wuliu.common.core.domain.entity.SysAppletUser;
import com.wuliu.common.utils.DateUtils;

import javax.annotation.Resource;

import com.wuliu.common.utils.SecurityUtils;
import com.wuliu.common.utils.StringUtils;
import com.wuliu.common.utils.ThreadLocalContext;
import com.wuliu.system.domain.*;
import com.wuliu.system.domain.dto.BaseDto;
import com.wuliu.system.domain.dto.app.LoadingDto;
import com.wuliu.system.mapper.TspLoadingTrackMapper;
import com.wuliu.system.mapper.TspOrderMapper;
import com.wuliu.system.service.IBasFilesService;
import com.wuliu.system.service.ITspLoadingDetailService;
import com.wuliu.system.service.ITspTrackService;
import org.springframework.stereotype.Service;
import com.wuliu.system.mapper.TspLoadingMapper;
import com.wuliu.system.service.ITspLoadingService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 装车单Service业务层处理
 *
 * @author realue
 * @date 2023-10-25
 */
@Service
public class TspLoadingServiceImpl extends ServiceImpl<TspLoadingMapper, TspLoading> implements ITspLoadingService {
    @Resource
    private TspLoadingMapper tspLoadingMapper;
    @Resource
    private TspOrderMapper tspOrderMapper;
    @Resource
    private ITspLoadingDetailService tspLoadingDetailService;
    @Resource
    private ITspTrackService tspTrackService;
    @Resource
    private IBasFilesService basFilesService;
    @Resource
    private TspLoadingTrackMapper tspLoadingTrackMapper;

    /**
     * 查询装车单
     *
     * @param id 装车单主键
     * @return 装车单
     */
    @Override
    public TspLoading selectTspLoadingById(String id) {
        return tspLoadingMapper.selectTspLoadingById(id);
    }

    /**
     * 查询装车单列表
     *
     * @param tspLoading 装车单
     * @return 装车单
     */
    @Override
    public List<TspLoading> selectTspLoadingList(TspLoading tspLoading) {
        return tspLoadingMapper.selectTspLoadingList(tspLoading);
    }

    /**
     * 新增装车单
     *
     * @param tspLoading 装车单
     * @return 结果
     */
    @Override
    public int insertTspLoading(TspLoading tspLoading) {
        tspLoading.setCreateTime(DateUtils.getNowDate());
        return tspLoadingMapper.insertTspLoading(tspLoading);
    }

    /**
     * 修改装车单
     *
     * @param tspLoading 装车单
     * @return 结果
     */
    @Override
    public int updateTspLoading(TspLoading tspLoading) {
        tspLoading.setUpdateTime(DateUtils.getNowDate());
        return tspLoadingMapper.updateTspLoading(tspLoading);
    }

    /**
     * 批量删除装车单
     *
     * @param ids 需要删除的装车单主键
     * @return 结果
     */
    @Override
    public int deleteTspLoadingByIds(String[] ids) {
        return tspLoadingMapper.deleteTspLoadingByIds(ids);
    }

    /**
     * 删除装车单信息
     *
     * @param id 装车单主键
     * @return 结果
     */
    @Override
    public int deleteTspLoadingById(String id) {
        return tspLoadingMapper.deleteTspLoadingById(id);
    }

    /**
     * 获取当前用户装车单
     *
     * @return
     */
    @Override
    public PageResult<TspLoading> getLoadingList(BaseDto dto) {
        SysAppletUser user = SecurityUtils.getAppletUser();
        Page page = PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<TspLoading> tspLoadings = tspLoadingMapper.selectList(new LambdaQueryWrapper<TspLoading>()
                .eq(TspLoading::getSysAccount, user.getSysAccount())
                .eq(TspLoading::getOpUserId, user.getUserId())
                .orderByDesc(TspLoading::getCreateTime));
        return new PageResult<>(page, tspLoadings);
    }

    /**
     * 创建跟车单
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean createLoading(LoadingDto dto) {
        SysAppletUser user = SecurityUtils.getAppletUser();
        List<String> orderNos = dto.getOrderNos().stream().distinct().collect(Collectors.toList());
        List<TspLoadingDetail> loadingDetails = new ArrayList<>();
        List<TspTrack> tracks = new ArrayList<>();
        List<TspOrder> orders = tspOrderMapper.selectList(new LambdaQueryWrapper<TspOrder>()
                .eq(TspOrder::getSysAccount, user.getSysAccount())
                .in(TspOrder::getOrderNo, orderNos));
        BigDecimal[] weight = {BigDecimal.ZERO};
        BigDecimal[] volume = {BigDecimal.ZERO};
        Integer[] cargoCnt = {0};
        String id = IdUtil.randomUUID();
        String loadNo = IdUtil.getSnowflakeNextIdStr();
        TspLoading tspLoading = new TspLoading();
        tspLoading.setId(id);
        tspLoading.setSysAccount(user.getSysAccount());
        tspLoading.setCreateBy(user.getUserName());
        tspLoading.setCreateTime(DateUtils.getNowDate());
        tspLoading.setOpUserId(user.getUserId());
        tspLoading.setOpUserName(user.getUserName());
        tspLoading.setLoadNo(loadNo);
        tspLoading.setPlateNumber(dto.getPlateNumber());
        tspLoading.setDriverId(dto.getDriverId());
        tspLoading.setDriverName(dto.getDriverName());
        tspLoading.setDriverTel(dto.getDriverTel());
        tspLoading.setSrcDeptId(dto.getSrcDeptId());
        tspLoading.setSrcDeptName(dto.getSrcDeptName());
        tspLoading.setDstDeptId(dto.getDstDeptId());
        tspLoading.setDstDeptName(dto.getDstDeptName());
        tspLoading.setStatus(OrderConstants.LOADING_STATUS_1);
        TspLoadingTrack loadingTrack = new TspLoadingTrack();
        String trackId = IdUtil.randomUUID();
        loadingTrack.setId(trackId);
        loadingTrack.setLoadNo(loadNo);
        loadingTrack.setOpCode(OrderConstants.LOADING_STATUS_1);
        loadingTrack.setOpTime(DateUtils.getTime());
        loadingTrack.setOpUserId(user.getUserId());
        loadingTrack.setOpUserName(user.getUserName());
        loadingTrack.setOpLng(dto.getLng());
        loadingTrack.setOpLat(dto.getLat());
        loadingTrack.setDeptId(user.getDeptId());
        loadingTrack.setDeptName(user.getDeptName());
        loadingTrack.setNextDeptId(dto.getDstDeptId());
        loadingTrack.setNextDeptName(dto.getDstDeptName());
        loadingTrack.setSysAccount(user.getSysAccount());
        loadingTrack.setCreateBy(user.getUserName());
        loadingTrack.setCreateTime(DateUtils.getNowDate());
        loadingTrack.setOperation("");
        if (StringUtils.isNotEmpty(dto.getPhotos())) {
            List<BasFiles> files = dto.getPhotos().stream().map(photo -> {
                BasFiles basFiles = new BasFiles();
                basFiles.setRelationId(trackId);
                basFiles.setId(IdUtil.randomUUID());
                basFiles.setType(1);
                basFiles.setFileType(OrderConstants.ORDER_STATUS_1);
                basFiles.setFileUrl(photo);
                basFiles.setSysAccount(user.getSysAccount());
                basFiles.setCreateTime(DateUtils.getNowDate());
                basFiles.setCreateBy(user.getUserName());
                return basFiles;
            }).collect(Collectors.toList());
            basFilesService.saveBatch(files);
        }
        if (StringUtils.isNotEmpty(orderNos)) {
            orderNos.forEach(item -> {
                TspLoadingDetail tspLoadingDetail = new TspLoadingDetail();
                tspLoadingDetail.setId(IdUtil.randomUUID());
                tspLoadingDetail.setSysAccount(user.getSysAccount());
                tspLoadingDetail.setCreateTime(DateUtils.getNowDate());
                tspLoadingDetail.setCreateBy(user.getUserName());
                tspLoadingDetail.setLoadId(id);
                tspLoadingDetail.setOrderNo(item);
                TspTrack tspTrack = new TspTrack();
                tspTrack.setId(IdUtil.randomUUID());
                tspTrack.setSysAccount(user.getSysAccount());
                tspTrack.setCreateBy(user.getUserName());
                tspTrack.setOpLat(dto.getLat());
                tspTrack.setOpLng(dto.getLng());
                tspTrack.setOrderNo(item);
                tspTrack.setOpCode(OrderConstants.ORDER_STATUS_2);
                tspTrack.setOpTime(DateUtils.getTime());
                tspTrack.setOpUserId(user.getUserId());
                tspTrack.setOpUserName(user.getUserName());
                tspTrack.setDeptId(user.getDeptId());
                tspTrack.setDeptName(user.getDeptName());
                tspTrack.setNextDeptId(dto.getDstDeptId());
                tspTrack.setNextDeptName(dto.getDstDeptName());
                tspTrack.setPlateNumber(dto.getPlateNumber());
                tspTrack.setDriverId(dto.getDriverId());
                tspTrack.setDriverName(dto.getDriverName());
                tspTrack.setOperation("");
                orders.stream().filter(t -> t.getOrderNo().equals(item)).findFirst().ifPresent(one -> {
                    tspTrack.setOrderId(one.getId());
                    tspLoadingDetail.setLength(one.getLength());
                    tspLoadingDetail.setHeight(one.getHeight());
                    tspLoadingDetail.setWidth(one.getWidth());
                    tspLoadingDetail.setWeight(one.getWeight());
                    tspLoadingDetail.setVolume(one.getVolume());
                    tspLoadingDetail.setCargoCnt(one.getCargoCnt());
                    tspLoadingDetail.setStatus(1);
                    weight[0] = weight[0].add(one.getWeight());
                    volume[0] = volume[0].add(one.getVolume());
                    cargoCnt[0] = cargoCnt[0] + one.getCargoCnt();
                });
                loadingDetails.add(tspLoadingDetail);
                tracks.add(tspTrack);
            });
        }
        tspTrackService.saveBatch(tracks);
        tspLoadingDetailService.saveBatch(loadingDetails);
        tspLoadingTrackMapper.insertTspLoadingTrack(loadingTrack);
        tspLoading.setGoodsCnt(cargoCnt[0]);
        tspLoading.setGoodsVolume(volume[0]);
        tspLoading.setGoodsWeight(weight[0]);
        tspLoadingMapper.insertTspLoading(tspLoading);
        return true;
    }
}
